#include "inc/dev_axp173.h"
#include "driver/i2c.h"


void axp173_SendByte(uint8_t reg_addr, uint8_t cmd)
{
	i2c_cmd_handle_t cmd_obj = i2c_cmd_link_create();

	i2c_master_start(cmd_obj);					//起始信号
   	i2c_master_write_byte(cmd_obj, ((AXP173_IIC_ADDR << 1) | I2C_MASTER_WRITE), 0x1);	//从机地址及读写位
    i2c_master_write_byte(cmd_obj, reg_addr, 0x1);	
    i2c_master_write_byte(cmd_obj, cmd, 0x1);	
    i2c_master_stop(cmd_obj);

    i2c_master_cmd_begin(common_i2c_num, cmd_obj, 100 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd_obj);
}

uint8_t axp173_RecsByte(uint8_t reg_addr)
{
    uint8_t data;
	i2c_cmd_handle_t cmd_obj = i2c_cmd_link_create();
	i2c_master_start(cmd_obj);					//起始信号
   	i2c_master_write_byte(cmd_obj, ((AXP173_IIC_ADDR << 1) | I2C_MASTER_WRITE), 0x1);	//从机地址及读写位
    i2c_master_write_byte(cmd_obj, reg_addr, 0x1); 
    
    i2c_master_start(cmd_obj);
    i2c_master_write_byte(cmd_obj, ((AXP173_IIC_ADDR << 1) | I2C_MASTER_READ), 0x1);
    i2c_master_read_byte(cmd_obj,&data, I2C_MASTER_NACK);
   	i2c_master_stop(cmd_obj);					//终止信号

    i2c_master_cmd_begin(common_i2c_num, cmd_obj, 100 / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(cmd_obj);
    return data;
}


int axp173_RecsByte_12bits(uint8_t reg_addr, uint8_t* res)
{
	i2c_cmd_handle_t cmd_obj = i2c_cmd_link_create();
	i2c_master_start(cmd_obj);					//起始信号
	i2c_master_write_byte(cmd_obj, ((AXP173_IIC_ADDR << 1) | I2C_MASTER_WRITE), 0x1);	//从机地址及读写位
	i2c_master_write_byte(cmd_obj, reg_addr, 0x1);

	i2c_master_start(cmd_obj);
	i2c_master_write_byte(cmd_obj, ((AXP173_IIC_ADDR << 1) | I2C_MASTER_READ), 0x1);
	i2c_master_read_byte(cmd_obj,res, I2C_MASTER_ACK);
	i2c_master_read_byte(cmd_obj,(res+1), I2C_MASTER_NACK);
	i2c_master_stop(cmd_obj);					//终止信号

	i2c_master_cmd_begin(common_i2c_num, cmd_obj, 100 / portTICK_PERIOD_MS);
	i2c_cmd_link_delete(cmd_obj);
	return 0;
}

inline uint16_t _getMin(uint16_t a, uint16_t b) {
    return ((a)<(b)?(a):(b));
}

inline uint16_t _getMax(uint16_t a, uint16_t b) {
    return ((a)>(b)?(a):(b));
}

inline uint16_t _getMid(uint16_t input, uint16_t min, uint16_t max) {
    return _getMax(_getMin(input, max), min);
}


uint8_t _I2C_read8Bit(uint8_t reg_addr)
{
    #if axp173_sim_iic_enable
        return axp173_simiic_ReadByte(reg_addr);
    #else
        return axp173_RecsByte(reg_addr);
    #endif
}
void _I2C_write1Byte(uint8_t add, uint8_t data)
{
    #if axp173_sim_iic_enable
        axp173_simiic_SendByte(add, data);
    #else
        axp173_SendByte(add, data);
    #endif    
}

uint16_t _I2C_read12Bit(uint8_t addr) {
	uint8_t ret[2];
	uint16_t res = 0;
	axp173_RecsByte_12bits(addr, ret);
	res |= ret[0] << 4;
	res |= ret[1] & 0x0f;
	return res;
}


void axp173_setOutputEnable(OUTPUT_CHANNEL channel, bool state) {
    uint8_t buff = _I2C_read8Bit(0x12); //buff类型为unsigned char
    buff = state ? ( buff | (1U << channel) ) : ( buff & ~(1U << channel) );
    _I2C_write1Byte(0x12, buff);        //对0x12寄存器写入1字节也就是8位二进制buff
}

void axp173_setOutputVoltage(OUTPUT_CHANNEL channel, uint16_t voltage) {
    uint8_t buff = 0;
    switch (channel) {
        case OP_DCDC1:
            voltage = (_getMid(voltage, 700, 3500) - 700) / 25; //0 - 112(step)
            buff = _I2C_read8Bit(0x26);
            buff = (buff & 0B10000000) | (voltage & 0B01111111);
            _I2C_write1Byte(0x26, buff);
            break;
        case OP_DCDC2:
            voltage = (_getMid(voltage, 700, 2275) - 700) / 25;
            buff = _I2C_read8Bit(0x23);
            buff = (buff & 0B11000000) | (voltage & 0B00111111);
            _I2C_write1Byte(0x23, buff);
            break;
        case OP_LDO2:
            voltage = (_getMid(voltage, 1800, 3300) - 1800) / 100;
            buff = _I2C_read8Bit(0x28);
            buff = (buff & 0B00001111) | (voltage << 4);
            _I2C_write1Byte(0x28, buff);
            break;
        case OP_LDO3:
            voltage = (_getMid(voltage, 1800, 3300) - 1800) / 100;
            buff = _I2C_read8Bit(0x28);
            buff = (buff & 0B11110000) | (voltage);
            _I2C_write1Byte(0x28, buff);
            break;
        case OP_LDO4:
            voltage = (_getMid(voltage, 700, 3500) - 700) / 25;
            buff = _I2C_read8Bit(0x27);
            buff = (buff & 0B10000000) | (voltage & 0B01111111);
            _I2C_write1Byte(0x27, buff);
            break;
        default:
            break;
    }
}

void axp173_setADCEnable(ADC_CHANNEL channel, bool state) {
	uint8_t buff = _I2C_read8Bit(0x82);
	buff = state ? ( buff | (1U << channel) ) : ( buff & ~(1U << channel) );
	_I2C_write1Byte(0x82, buff);
}
void axp173_setChipTempEnable(bool state) {
	uint8_t buff = _I2C_read8Bit(0x83);
	buff = state ? ( buff | 0B10000000 ) : ( buff & 0B01111111 );
	_I2C_write1Byte(0x83, buff);
}

float axp173_getBatVoltage(void) {
	float ADCLSB = 1.1f / 1000.0f;
	return _I2C_read12Bit(0x78) * ADCLSB;
}
float axp173_getAXP173Temp(void) {
	float ADCLSB = 0.1f;
	const float OFFSET_DEG_C = -144.7f;
	uint16_t ReData = _I2C_read12Bit(0x5E);
	return OFFSET_DEG_C + ReData * ADCLSB;
}
float axp173_getBatLevel(void) {
	const float batVoltage = axp173_getBatVoltage();
	const float batPercentage = (batVoltage < 3.248088) ? (0) : (batVoltage - 3.120712) * 100;
	return (batPercentage <= 100) ? batPercentage : 100;
}

void axp173_setoutPWR(void)
{
	axp173_setChipTempEnable(true);
	axp173_setADCEnable(ADC_BAT_V, true);
	axp173_setADCEnable(ADC_BAT_C, true);
	axp173_setADCEnable(ADC_VBUS_C, true);
	axp173_setADCEnable(ADC_VBUS_V, true);

    #if LDO2_ENABLE
    axp173_setOutputEnable(OP_LDO2, true);     //LDO2设置为输出
    axp173_setOutputVoltage(OP_LDO2, LDO2_VOL);    //LDO2电压设置为3.000V
    #endif
    #if LDO3_ENABLE 
    axp173_setOutputEnable(OP_LDO3, true);     //LDO3设置为输出
    axp173_setOutputVoltage(OP_LDO3, LDO3_VOL);    //LDO3电压设置为3.300V
    #endif
    #if LDO4_ENABLE
    axp173_setOutputEnable(OP_LDO4, true);     //LDO4设置为输出
    axp173_setOutputVoltage(OP_LDO4, LDO4_VOL);    //LDO4电压设置为3.300V
    #endif
    #if DCDC1_ENABLE
    axp173_setOutputEnable(OP_DCDC1, true);    //DCDC1设置为输出
    axp173_setOutputVoltage(OP_DCDC1, DCDC1_VOL);   //DCDC1电压设置为3.300V
    #endif
    #if DCDC2_ENABLE
    axp173_setOutputEnable(OP_DCDC2, true);    //DCDC2设置为输出
    axp173_setOutputVoltage(OP_DCDC2, 2275);   //DCDC2电压设置为2.275V
    #endif
        
}

void axp173_init(void)
{
    axp173_setoutPWR();
}
